﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.Diagnostics;
using System.IO;

namespace mqtt_app
{
   
    public partial class Form2 : Form
    {
        public struct iot_proctrl_data_frame
        {
            public byte[] start_tag;
            public long fram_NO;
            public long protocol_type;
            public long Dev_Add;
            public long Dev_type;
            public byte Interaction_tag;
            public long data_len;
            public byte Cmd;

            public byte[] data_table;
            public byte crc_sum8;
        };
        iot_proctrl_data_frame uart_frame = new iot_proctrl_data_frame();
        FileStream fsread;
        bool IsSerialPortOpen;
        public Form2()
        {
            InitializeComponent();
        }
        private void sherch_serialPort()
        {
            foreach (string s in System.IO.Ports.SerialPort.GetPortNames())
            {//获取有多少个COM口
                System.Diagnostics.Debug.WriteLine(s);

                comboBox1.Items.Add(s);
            }
        }
        private void OutMsg(TextBox rtb, string msg, Color color)
        {
            rtb.Invoke(new EventHandler(delegate
            {
                rtb.SelectionStart = rtb.Text.Length;//设置插入符位置为文本框末
                //rtb.SelectionColor = color;//设置文本颜色
                rtb.AppendText(msg + "\r\n");//输出文本，换行
                rtb.ScrollToCaret();//滚动条滚到到最新插入行
            }));
        }
        private void Form2_Load(object sender, EventArgs e)
        {
            sherch_serialPort();
            comboBox2.Text = "115200";
            comboBox3.Text = "8";
            comboBox4.Text = "1";
            comboBox5.SelectedIndex = 1;
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void label2_Click(object sender, EventArgs e)
        {

        }

        private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void label4_Click(object sender, EventArgs e)
        {

        }

        private void comboBox4_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (IsSerialPortOpen == false)
            {
                if (comboBox1.Text != "")
                {
                    sp1.PortName = comboBox1.Text;
                    if (comboBox2.Text != "")
                    {
                        sp1.BaudRate = Convert.ToInt32(comboBox2.Text);

                        if (comboBox3.Text != "")
                        {
                            sp1.DataBits = Convert.ToInt32(comboBox3.Text);
                            if (comboBox4.Text != "")
                            {
                                if (comboBox4.Text == "0")
                                    sp1.StopBits = StopBits.None;
                                if (comboBox4.Text == "1")
                                    sp1.StopBits = StopBits.One;
                                if (comboBox4.Text == "1.5")
                                    sp1.StopBits = StopBits.OnePointFive;
                                if (comboBox4.Text == "2")
                                    sp1.StopBits = StopBits.Two;
                                sp1.DataReceived += new SerialDataReceivedEventHandler(sp1_DataReceived);
                                try
                                {
                                    sp1.Open();     //打开串口

                                }
                                catch(Exception ex)
                                {
                                    throw new Exception(ex.ToString());
                                }
                                finally
                                {

                                }
                                button1.Text = "关闭串口";
                                IsSerialPortOpen = true;
                            }

                        }
                    }

                }
                else
                    return;
                //axMSComm1.CommPort = 3;
                //axMSComm1.PortOpen = true;
                //button2.Text = "关闭串口";
                //IsSerialPortOpen = true;

            }
            else
            {
                sp1.Close();     //打开串口
                button1.Text = "打开串口";
                // axMSComm1.PortOpen = false;
                IsSerialPortOpen = false;
                clear_all_data();
            }
        }
        private long received_count = 0;//接收计数   
        List<string> receiveString = new List<string>();
        StringBuilder builder = new StringBuilder();
        int pbar_val = 0;
        int pkgs = 0;
        int remian = 0;
        int pkg_count = 0;
        private long file_len = 0;
        private void clear_all_data()
        {
            if (fsread != null)
                fsread.Close();
            pbar_val = 0;
            pkgs = 0;
            remian = 0;
            pkg_count = 0;
            file_len = 0;
        }
        private void serial_port_send_file(long pkg_index,int data_lenth)
        {
            byte[] send_buf = new byte[522];
            byte[] heByte = new byte[512];
            int read_lenth = 0;
            if (pkg_count < pkgs)
                read_lenth = 512;
            else
                read_lenth = remian;
            int y=  fsread.Read(heByte, 0, read_lenth);
            
            int datalen = 0;
            byte sum = 0;
            int i = 0;
            send_buf[datalen++] = 0x24;
            send_buf[datalen++] = 0x24;
            send_buf[datalen++] = 0x01;
            send_buf[datalen++] = (byte)read_lenth;//数据域长度
            send_buf[datalen++] = (byte)(read_lenth >> 8);
            send_buf[datalen++] = 0x88;
            for (i = 0; i < read_lenth; i++)
                send_buf[datalen++] = heByte[i];
            for ( i = 2; i < datalen; i++)
                sum += send_buf[i];
            send_buf[datalen++] = sum;
            send_buf[datalen++] = 0x35;
            send_buf[datalen++] = 0x35;
            pbar_val += read_lenth;
            if (pbar_val >= file_len)
                return;
            pkg_count++;
            
            Debug.WriteLine("已发送：" + pbar_val.ToString()+"pkgs:"+ pkg_count.ToString());
            sp1.Write(send_buf, 0, datalen);
            
        }
        
        private void uart_data_process(byte [] data,long data_len)
        {
            long i = 0, k = 0;
            byte sum = 0;
            byte check_sum = 0;
            long frame_data_area_len = 0;
            
            for (i = 0; i < data_len; i++)
            {
                if (data[i] == 0x24)
                {
                    if ((data[data_len - 1] == 0x35) && (data[data_len - 1] == 0x35))
                    {
                        //printf("fond frame start and end\r\n");
                        uart_frame.data_len = (long)data[4] << 8 | (long)data[3];
                        uart_frame.Cmd = data[5];
                        Debug.WriteLine("data_len:"+ uart_frame.data_len.ToString()+ "cmd:"+ uart_frame.Cmd.ToString());
                        switch (uart_frame.Cmd) 
                        {
                            case 0x87://收到设备升级响应，开始发送文件的第一个包
                                button1.Enabled = false;
                                button2.Enabled = false;
                                button4.Enabled = false;
                                button5.Enabled = false;
                                button6.Enabled = false;
                                serial_port_send_file(pkg_count, 512);
                                
                                break;

                            case 0x88://收到设备升级响应，正常分包发送升级文件

                                progressBar1.Invoke((EventHandler)(delegate
                                {
                                    progressBar1.Value = (int)(pbar_val * 100 / file_len );
                                }));
                                if (pbar_val >= file_len)
                                {
                                    OutMsg(textBox1,"文件发送完毕",Color.White);
                                    //MessageBox.Show("文件发送完毕");
                                    button1.Enabled = true;
                                    button2.Enabled = true;
                                    button4.Enabled = true;
                                    button5.Enabled = true;
                                    button6.Enabled = true;
                                    clear_all_data();
                                }
                                else
                                    serial_port_send_file(pkg_count,(int) (file_len - (pkg_count * 512)) % 512);
                                
                                break;
                            default:

                                break;
                        }
                        return;
                    }
                    else
                        return;

                }

            }
            
        }
        private void sp1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {

            int temp, frq, max;
            int n = sp1.BytesToRead;//先记录下来，避免某种原因，人为的原因，操作几次之间时间长，缓存不一致  
            if (n >2)
            {
                byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据 

                received_count += n;//增加接收计数  
                sp1.Read(buf, 0, n);//读取缓冲数据  
                builder.Clear();//清除字符串构造器的内容  
                                //因为要访问ui资源，所以需要使用invoke方式同步ui。
                Encoding utf8encoding = Encoding.UTF8;
                Encoding gbcoding = Encoding.GetEncoding("GB2312");
                this.Invoke((EventHandler)(delegate
                {
                    //判断是否是显示为16禁止  
                    //if (checkBoxHexView.Checked)
                    //{
                    //    //依次的拼接出16进制字符串  
                    //foreach (byte b in buf)
                    //{
                    //    builder.Append(b.ToString("X2") + " ");
                    //}
                    //}
                    // else
                    //{
                    //    //直接按ASCII规则转换成字符串  
                       builder.Append(Encoding.ASCII.GetString(buf));

                    //}
                    //追加的形式添加到文本框末端，并滚动到最后。 
                    //this.textBox1.Text += DateTime.Now.ToString() + " " + (gbcoding.GetString(buf)) + "\r\n\r\n";
                    //修改接收计数  
                    //this.textBox1.ScrollToCaret();
                    OutMsg(textBox1, DateTime.Now.ToString() + " " + (gbcoding.GetString(buf)), Color.Green);
                    uart_data_process(buf,n);
                }));


            }
        }
        
        private void button3_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                System.IO.Path.GetFullPath(openFileDialog1.FileName);                             //绝对路径
                System.IO.Path.GetExtension(openFileDialog1.FileName);                           //文件扩展名
                System.IO.Path.GetFileNameWithoutExtension(openFileDialog1.FileName);//文件名没有扩展  名
                System.IO.Path.GetFileName(openFileDialog1.FileName);                          //得到文件
                System.IO.Path.GetDirectoryName(openFileDialog1.FileName);                  //得到路径
                Debug.WriteLine(openFileDialog1.FileName);
                textBox3.Text= openFileDialog1.FileName;

                
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            //   24 24 01 03 00 88 01 02 03  35 35
            if (textBox3.Text == "")
                return;
            clear_all_data();
            FileInfo fi = new FileInfo(textBox3.Text);
            file_len = fi.Length;
            Debug.WriteLine(fi.Length);
            fsread = new FileStream(textBox3.Text, FileMode.Open);
            //byte[] heByte = new byte[512];
            //int r = fsread.Read(heByte, 0, heByte.Length);
            pkgs = (int)(file_len / 512);
            remian = (int)(file_len % 512);

            byte[] send_buf = new byte[64];
            int datalen =0;
            byte sum = 0;
            
            send_buf[datalen++] = 0x24;
            send_buf[datalen++] = 0x24;
            send_buf[datalen++] = 0x01;
            send_buf[datalen++] = 0x04;//数据域长度
            send_buf[datalen++] = 0x00;
            send_buf[datalen++] = 0x87;
            send_buf[datalen++] = (byte)(file_len) ;
            send_buf[datalen++] = (byte)(file_len >> 8);
            send_buf[datalen++] = (byte)(file_len >> 16);
            send_buf[datalen++] = (byte)(file_len >> 24);
            for (int i = 2; i < datalen; i++)
                sum += send_buf[i];
            send_buf[datalen++] = sum;
            send_buf[datalen++] = 0x35;
            send_buf[datalen++] = 0x35;

            sp1.Write(send_buf,0,datalen);
        }
        
        private void Form2_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (IsSerialPortOpen == true)
            {
                sp1.Close();
                IsSerialPortOpen = false;
            }
            clear_all_data();
        }
        void cmd_pakage(string cmd_data,int cmd_len)
        {
            byte[] send_buf = new byte[64];
            byte[] send_cmd = Encoding.Default.GetBytes(cmd_data);
            int datalen = 0;
            byte sum = 0;

            send_buf[datalen++] = 0x24;
            send_buf[datalen++] = 0x24;
            send_buf[datalen++] = 0x01;
            send_buf[datalen++] = (byte)cmd_len;//数据域长度
            send_buf[datalen++] = (byte)(cmd_len>>8);
            send_buf[datalen++] = 0x87;//cmd
            for (int i = 0; i < cmd_len; i++)
                send_buf[datalen++] = send_cmd[i];
            for (int i = 2; i < datalen; i++)
                sum += send_buf[i];
            send_buf[datalen++] = sum;
            send_buf[datalen++] = 0x35;
            send_buf[datalen++] = 0x35;
            if (IsSerialPortOpen == true)
            {
                sp1.Write(send_buf, 0, datalen);
            }
        }
        private void button2_Click(object sender, EventArgs e)
        {
            string cmd = "100,2,123\r\n";
            cmd_pakage(cmd,cmd.Length);
            //byte[] send_cmd = Encoding.Default.GetBytes(cmd);
            //if(IsSerialPortOpen==true)
            //{
            //    sp1.Write(send_cmd, 0, cmd.Length);
            //}
        }

        private void button5_Click(object sender, EventArgs e)
        {
            if (comboBox5.Text != "")
            {
                string cmd = comboBox5.Text+"\r\n";
                cmd_pakage(cmd, cmd.Length);
            }
            else
                MessageBox.Show("命令不能为空");
        }

        private void button6_Click(object sender, EventArgs e)
        {
            string cmd = "100,2\r\n";
            byte[] send_buf = new byte[64];
            byte[] send_cmd = Encoding.Default.GetBytes(cmd);
            int datalen = 0;
            
            if (IsSerialPortOpen == true)
            {
                sp1.Write(send_cmd, 0, cmd.Length);
            }
        }
    }
}
